import { Injectable, Inject, Logger } from '@nestjs/common';
import type {
  MonitoringInterface,
  HealthCheckInterface,
  PerformanceMonitoringInterface,
  Timer,
  HealthStatus,
  HealthCheckResult,
  MonitoringOptions,
} from './monitoring.interface';

/**
 * 监控服务
 * 基于 NestJS 官方示例实现
 * 参考: https://docs.nestjs.cn/fundamentals/dependency-injection
 * 对应 Java: 监控服务
 */
@Injectable()
export class MonitoringService
  implements
    MonitoringInterface,
    HealthCheckInterface,
    PerformanceMonitoringInterface
{
  private readonly logger = new Logger(MonitoringService.name);
  private healthChecks = new Map<string, () => Promise<boolean>>();
  private startTime = Date.now();

  constructor(
    @Inject('MONITORING_PROVIDER')
    private readonly monitoringProvider: MonitoringInterface,
    @Inject('HEALTH_CHECK_PROVIDER')
    private readonly healthCheckProvider: HealthCheckInterface,
  ) {}

  // ==================== 基础监控接口 ====================

  /**
   * 记录计数器指标
   */
  counter(
    name: string,
    value: number = 1,
    labels?: Record<string, string>,
  ): void {
    try {
      this.monitoringProvider.counter(name, value, labels);
    } catch (error) {
      this.logger.error(`Failed to record counter: ${name}`, error);
    }
  }

  /**
   * 记录直方图指标
   */
  histogram(
    name: string,
    value: number,
    labels?: Record<string, string>,
  ): void {
    try {
      this.monitoringProvider.histogram(name, value, labels);
    } catch (error) {
      this.logger.error(`Failed to record histogram: ${name}`, error);
    }
  }

  /**
   * 记录摘要指标
   */
  summary(name: string, value: number, labels?: Record<string, string>): void {
    try {
      this.monitoringProvider.summary(name, value, labels);
    } catch (error) {
      this.logger.error(`Failed to record summary: ${name}`, error);
    }
  }

  /**
   * 记录仪表盘指标
   */
  gauge(name: string, value: number, labels?: Record<string, string>): void {
    try {
      this.monitoringProvider.gauge(name, value, labels);
    } catch (error) {
      this.logger.error(`Failed to record gauge: ${name}`, error);
    }
  }

  /**
   * 开始计时
   */
  startTimer(name: string, labels?: Record<string, string>): Timer {
    try {
      return this.monitoringProvider.startTimer(name, labels);
    } catch (error) {
      this.logger.error(`Failed to start timer: ${name}`, error);
      return {
        end: () => 0,
      };
    }
  }

  /**
   * 记录执行时间
   */
  async time<T>(
    name: string,
    fn: () => T | Promise<T>,
    labels?: Record<string, string>,
  ): Promise<T> {
    const timer = this.startTimer(name, labels);
    try {
      const result = await fn();
      return result;
    } finally {
      timer.end(labels);
    }
  }

  /**
   * 获取指标值
   */
  async getMetric(
    name: string,
    labels?: Record<string, string>,
  ): Promise<number | null> {
    try {
      return this.monitoringProvider.getMetric(name, labels);
    } catch (error) {
      this.logger.error(`Failed to get metric: ${name}`, error);
      return null;
    }
  }

  /**
   * 获取所有指标
   */
  async getMetrics(): Promise<string> {
    try {
      return this.monitoringProvider.getMetrics();
    } catch (error) {
      this.logger.error('Failed to get metrics', error);
      return '';
    }
  }

  /**
   * 重置指标
   */
  reset(name?: string): void {
    try {
      this.monitoringProvider.reset(name);
    } catch (error) {
      this.logger.error(`Failed to reset metrics: ${name || 'all'}`, error);
    }
  }

  // ==================== 健康检查接口 ====================

  /**
   * 检查健康状态
   */
  async check(): Promise<HealthStatus> {
    const checks: Record<string, HealthCheckResult> = {};
    let overallStatus: 'healthy' | 'unhealthy' | 'degraded' = 'healthy';
    const hasWarnings = false;

    for (const [name, checkFn] of this.healthChecks) {
      const startTime = Date.now();
      try {
        const isHealthy = await checkFn();
        const duration = Date.now() - startTime;

        checks[name] = {
          status: isHealthy ? 'pass' : 'fail',
          timestamp: Date.now(),
          duration,
        };

        if (!isHealthy) {
          overallStatus = 'unhealthy';
        }
      } catch (error) {
        const duration = Date.now() - startTime;
        checks[name] = {
          status: 'fail',
          message: error.message,
          timestamp: Date.now(),
          duration,
        };
        overallStatus = 'unhealthy';
      }
    }

    // 如果没有健康检查，默认为健康
    if (Object.keys(checks).length === 0) {
      checks['default'] = {
        status: 'pass',
        timestamp: Date.now(),
      };
    }

    return {
      status: overallStatus,
      timestamp: Date.now(),
      uptime: Date.now() - this.startTime,
      checks,
      version: process.env.npm_package_version,
      environment: process.env.NODE_ENV,
    };
  }

  /**
   * 注册健康检查
   */
  register(name: string, checkFn: () => Promise<boolean>): void {
    this.healthChecks.set(name, checkFn);
  }

  /**
   * 取消注册健康检查
   */
  unregister(name: string): void {
    this.healthChecks.delete(name);
  }

  // ==================== 性能监控接口 ====================

  /**
   * 记录请求
   */
  recordRequest(
    method: string,
    path: string,
    statusCode: number,
    duration: number,
    labels?: Record<string, string>,
  ): void {
    const requestLabels = {
      method,
      path,
      status_code: statusCode.toString(),
      ...labels,
    };

    // 记录请求计数
    this.counter('http_requests_total', 1, requestLabels);

    // 记录请求持续时间
    this.histogram(
      'http_request_duration_seconds',
      duration / 1000,
      requestLabels,
    );

    // 记录状态码分布
    this.counter('http_status_codes_total', 1, {
      status_code: statusCode.toString(),
      ...labels,
    });
  }

  /**
   * 记录数据库查询
   */
  recordDatabaseQuery(
    operation: string,
    table: string,
    duration: number,
    labels?: Record<string, string>,
  ): void {
    const dbLabels = {
      operation,
      table,
      ...labels,
    };

    // 记录查询计数
    this.counter('database_queries_total', 1, dbLabels);

    // 记录查询持续时间
    this.histogram(
      'database_query_duration_seconds',
      duration / 1000,
      dbLabels,
    );
  }

  /**
   * 记录缓存操作
   */
  recordCacheOperation(
    operation: string,
    key: string,
    hit: boolean,
    duration: number,
    labels?: Record<string, string>,
  ): void {
    const cacheLabels = {
      operation,
      hit: hit.toString(),
      ...labels,
    };

    // 记录缓存操作计数
    this.counter('cache_operations_total', 1, cacheLabels);

    // 记录缓存命中率
    this.counter('cache_hits_total', hit ? 1 : 0, cacheLabels);
    this.counter('cache_misses_total', hit ? 0 : 1, cacheLabels);

    // 记录缓存操作持续时间
    this.histogram(
      'cache_operation_duration_seconds',
      duration / 1000,
      cacheLabels,
    );
  }

  /**
   * 记录外部API调用
   */
  recordExternalApiCall(
    service: string,
    endpoint: string,
    statusCode: number,
    duration: number,
    labels?: Record<string, string>,
  ): void {
    const apiLabels = {
      service,
      endpoint,
      status_code: statusCode.toString(),
      ...labels,
    };

    // 记录API调用计数
    this.counter('external_api_calls_total', 1, apiLabels);

    // 记录API调用持续时间
    this.histogram(
      'external_api_call_duration_seconds',
      duration / 1000,
      apiLabels,
    );

    // 记录API状态码分布
    this.counter('external_api_status_codes_total', 1, {
      service,
      status_code: statusCode.toString(),
      ...labels,
    });
  }

  // ==================== 装饰器支持 ====================

  /**
   * 监控装饰器实现
   */
  async monitor<T>(
    options: MonitoringOptions,
    fn: () => T | Promise<T>,
  ): Promise<T> {
    const { name, type = 'histogram', labels, enabled = true } = options;

    if (!enabled || !name) {
      return await fn();
    }

    const timer = this.startTimer(name, labels);
    try {
      const result = await fn();
      return result;
    } finally {
      const duration = timer.end(labels);
      this.histogram(name, duration / 1000, labels);
    }
  }

  // ==================== 工具方法 ====================

  /**
   * 记录错误
   */
  recordError(error: Error, labels?: Record<string, string>): void {
    this.counter('errors_total', 1, {
      error_type: error.constructor.name,
      error_message: error.message,
      ...labels,
    });
  }

  /**
   * 记录内存使用
   */
  recordMemoryUsage(): void {
    const usage = process.memoryUsage();

    this.gauge('memory_usage_bytes', usage.heapUsed, { type: 'heap_used' });
    this.gauge('memory_usage_bytes', usage.heapTotal, { type: 'heap_total' });
    this.gauge('memory_usage_bytes', usage.external, { type: 'external' });
    this.gauge('memory_usage_bytes', usage.rss, { type: 'rss' });
  }

  /**
   * 记录CPU使用
   */
  recordCpuUsage(): void {
    const usage = process.cpuUsage();
    const total = usage.user + usage.system;

    this.gauge('cpu_usage_microseconds', total, { type: 'total' });
    this.gauge('cpu_usage_microseconds', usage.user, { type: 'user' });
    this.gauge('cpu_usage_microseconds', usage.system, { type: 'system' });
  }

  /**
   * 记录事件循环延迟
   */
  recordEventLoopDelay(): void {
    const start = process.hrtime.bigint();
    setImmediate(() => {
      const delay = Number(process.hrtime.bigint() - start) / 1000000; // 转换为毫秒
      this.histogram('event_loop_delay_milliseconds', delay);
    });
  }

  /**
   * 记录垃圾回收
   */
  recordGarbageCollection(): void {
    if (global.gc) {
      const start = process.hrtime.bigint();
      global.gc();
      const duration = Number(process.hrtime.bigint() - start) / 1000000; // 转换为毫秒
      this.histogram('gc_duration_milliseconds', duration);
    }
  }

  /**
   * 启动默认指标收集
   */
  startDefaultMetrics(): void {
    // 记录内存使用
    setInterval(() => {
      this.recordMemoryUsage();
    }, 10000); // 每10秒

    // 记录CPU使用
    setInterval(() => {
      this.recordCpuUsage();
    }, 10000); // 每10秒

    // 记录事件循环延迟
    setInterval(() => {
      this.recordEventLoopDelay();
    }, 5000); // 每5秒

    this.logger.log('Default metrics collection started');
  }
}
